import UIKit
// 遵循FloatingPoint协议说明他是浮点数 不用再转换类型例如:Float(CGFloat类型的数)

/// 返回斜边值
/// - Parameters:
///   - a: 直角边
///   - b: 直角边
/// - Returns: 三角形返回斜边
func hypotenuse(_ a: Float, _ b: Float) -> Float {
    return (a * a + b * b).squareRoot()
}

let afloat: Float = 3.0
let bfloat: Float = 4.0

hypotenuse(afloat, bfloat)

let acgfloat: CGFloat = 3.0
let bcgfloat: CGFloat = 4.0
// hypotenuse(acgfloat, bcgfloat) ❎Cannot convert value of type 'CGFloat' to expected argument type 'Float'
// hypotenuse(Float(acgfloat), Float(bcgfloat))✅

func anotherHypotenuse<T: FloatingPoint>(_ a: T, _ b: T) -> T {
    return (a * a + b * b).squareRoot()
}

anotherHypotenuse(acgfloat, bcgfloat)

let aDouble: Double = 3.0
let bDouble: Double = 4.0
anotherHypotenuse(aDouble, bDouble)

// pi
let alpha: Float = 2.0
alpha * .pi // Float.pi 自动识别

let beta: Double = 3
beta * .pi // Double.pi

func minf<T: FloatingPoint>(_ a: [T]) -> T {
    var m = T.infinity

    for i in a {
        if i < m {
            m = i
        }
    }
    return m
}

/*
 在 Swift 中，FloatingPoint.infinity 是一个表示无穷大的特殊浮点数值。FloatingPoint 是一个协议，它定义了一些基本的行为和属性，这些行为和属性对于遵循该协议的浮点类型（如 Float 和 Double）都是通用的。

 FloatingPoint.infinity 的主要作用如下：

 表示无法表示的大数值：当某个计算的结果超出了浮点数的表示范围时，它可能会返回 infinity。例如，当你尝试将一个非常大的正数除以一个非常小的正数时，结果可能会是 infinity。
 数学运算：虽然 infinity 不是一个普通的数字，但它仍然可以参与一些数学运算。例如，任何正数加上 infinity 都会得到 infinity；任何非零的数除以 infinity 都会得到 0；而 infinity 除以任何非零的数都会得到 infinity（但符号取决于除数的符号）。但是，需要注意的是，infinity 与 infinity 的运算（如加法、减法或乘法）通常是未定义的，并且可能会导致 NaN（不是一个数字）的结果。
 错误处理：在某些情况下，infinity 可以被用作一种错误处理机制。例如，如果你正在编写一个需要计算两个点之间距离的函数，并且这两个点是相同的，那么理论上距离应该是 0。但是，如果你的函数在计算过程中出现了错误（例如，除以了零），那么它可能会返回 infinity，从而提示调用者出现了问题。

 需要注意的是，虽然 FloatingPoint.infinity 是一个很有用的工具，但在实际编程中应该尽量避免依赖于它。在许多情况下，更好的做法是使用条件语句来检查可能出现的错误情况，并在出现问题时返回适当的错误代码或抛出异常。
 */

// NAN(not a number)
let m1 = Double.nan
m1 > 0 // false
m1 <= 0 // false

func divide<T: FloatingPoint>(_ a: T, _ b: T) -> T {
    if b.isZero {
        return T.nan
    }
    return a / b
}

// 判断nan
divide(2.9, 0.0).isNaN // NAN

let temperatureData = ["21.5", "19.25", "27", "no data", "28.25", "no data", "24"]

let tempsCelsius = temperatureData.map { Double($0) }
print(tempsCelsius.first)
let first = tempsCelsius[2] // Double? nil
let first_2 = tempsCelsius.first // Double??

let tempsCelsiusNan = temperatureData.map { Double($0) ?? .nan }

let tempsFahrenheit = tempsCelsiusNan.map { $0 * 1.8 + 32 }
print(tempsFahrenheit)
// NaN任意运算都是NaN
let badAverage = tempsFahrenheit.reduce(0.0, +) / Double(tempsFahrenheit.count) // NaN

// 筛选非NaN
let validTemps = tempsFahrenheit.filter { !$0.isNaN }

let average = validTemps.reduce(0, +) / Double(validTemps.count)

let items = [1, 2, 3]
items.forEach { item in
    if item == 2 { return }
    //	item * 2
    print("foreach:" + "\(item)") // item==2不执行此句,但仍会执行下次循环.(foreach中使用return不会跳出函数,效果如break
}

print(items) // [1, 2, 3] foreach不会影响items
// forEach不可以提前退出循环吗
// 是的，你说得对 。 forEach 函数在 Swift 中并不提供直接的方式来提前退出循环 。 forEach 是一个高阶函数，它接受一个闭包作为参数，并对集合中的每个元素执行这个闭包 。 由于 forEach 并不是基于控制流的循环语句（如 for- in、 while 或 repeat -while），所以它没有内置的 break 或 continue 语句来提前退出或跳过迭代。
//
// 如果你需要在遍历过程中提前退出，你应该使用 for- in 循环或其他控制流语句 。 例如：
//
// swift
// let numbers = [1, 2, 3, 4, 5]
// for number in numbers {
//    if number == 3 {
//        break // 使用 break 提前退出循环
//    }
//    print(number)
// }
//
//// 输出: 1 2
//
// 在这个例子中，我们使用 for- in 循环来遍历数组 numbers，并使用 break 语句在 number 等于 3 时提前退出循环 。 这样，只有 1 和 2 会被打印出来。

// swift3 %求余操作只能对整数运行
let e = 5.235
let f = 2.3
// e%f
